package com.hugegreenbug.msoss;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.os.SystemClock;
import android.util.Log;

import com.hugegreenbug.msoss.Cube;
import com.rbgrn.net.GLWallpaperService;


public class MsRenderer implements GLSurfaceView.Renderer, GLWallpaperService.Renderer {
	private float[] lightAmbient = {0.0f, 0.0f, 0.0f, 1.0f};
	private float[] lightDiffuse = {1.0f, 1.0f, 1.0f, 1.0f};
	private float[] lightPosition = {0.0f, 0.0f, 2.0f, 1.0f};
	private FloatBuffer lightAmbientBuffer;
	private FloatBuffer lightDiffuseBuffer;
	private FloatBuffer lightPositionBuffer;
	private static final long ERROR_STD = 300000;    //Milliseconds to restart download for a serious error
	public static final int RELEASE_WALL_TEX = 1;
 	public static final int RELEASE_CUBE_TEX = 2;
 	public static final int CUBE_MODE = 1;
 	public static final int WALL_MODE = 2;
 	public static final int ZOOM_MODE = 3;
 	public static final int STRETCH_MODE = 4;
 	private static final String[] DISK_ERROR = {"Could ", "not ", "find ", "a musician. ", 
		"Turn ", "off ", "disk ", "drive ", "mode ", "if it ", "is on. ",
		"Will ", "retry ", "in: " + ERROR_STD/(1000 * 60) + " ","minutes."};
	private static final String[] LOAD_MSG = {"Loading ..."};
	private static final String[] LOAD_ERROR = {"Could ", "not ", "load ", "an image. ", "Will ", 
		"retry ", "in: " + ERROR_STD/(1000 * 60) + " ", "minutes."};
	private static final String[] GENERIC_ERROR = {"An", " error", " occurred.", " Will", 
		" retry", " in: " + ERROR_STD/(1000 * 60), " minutes"};
	public static final int ERROR_NOERROR = 0;
 	public static final int ERROR_NOARTIST = 1;
 	public static final int ERROR_MAXRETRIES = 2;
 	public static final int ERROR_GENERIC = 3;
 	public static final int MAX_FADEIN = 255;
 	public static final int MAX_FADEOUT = 50;
 	private static final int FADE_DIFF = 4;
	private volatile int mRelease;
	private volatile Cube mCube;
	private volatile Wall mWall;
	private volatile Background mBackground;
	private volatile boolean mSleep;
	private volatile boolean mFirstImage;
	private volatile int mError;
	private Text mText;
	private volatile int mCanvasWidth;
	private volatile int mCanvasHeight;
	private volatile double mCanvasWidthThresh;
	private volatile double mCanvasHeightThresh;
	private GL10 mGL;
	private volatile WikiCommonsImage curWikiImage;
	private volatile WikiCommonsImage newWikiImage;
	private long mLastTextDisplay;
	private boolean mAnimateText;
	private boolean mLight;
	private volatile int mImageDisplay;
	private volatile int mClearColor;
	private float mClearColorR;
	private float mClearColorG;
	private float mClearColorB;
	private boolean mClearColorChanged;
	private volatile int mFadeOut;
	private volatile int mFadeIn;
	private volatile int mMaxTexSize;
	private float xrot, yrot, zrot;
    private float xtrans, ytrans;
    private int xtrans_dir, ytrans_dir;
	private volatile boolean mDisplayArtistImage;   
	private volatile boolean mDisplayArtistVisible;   
    private volatile boolean mCubeScale;
    private volatile float mTextSize;
    private volatile int mTextColor;
    private volatile float mCanvasRatio;
    private volatile boolean mSetBg;
    private volatile boolean mSettingBackground;
    private volatile boolean mTextChanged;
    private volatile boolean mSurfaceChanged;
    private volatile boolean mStretchBg;
    private volatile boolean mStretchWall;
    //private volatile long fpscounter;
    //private volatile long fpstime;
    
	public MsRenderer() {
		ByteBuffer byteBuf = ByteBuffer.allocateDirect(lightAmbient.length * 4);
		byteBuf.order(ByteOrder.nativeOrder());
		lightAmbientBuffer = byteBuf.asFloatBuffer();
		lightAmbientBuffer.put(lightAmbient);
		lightAmbientBuffer.position(0);
		
		byteBuf = ByteBuffer.allocateDirect(lightDiffuse.length * 4);
		byteBuf.order(ByteOrder.nativeOrder());
		lightDiffuseBuffer = byteBuf.asFloatBuffer();
		lightDiffuseBuffer.put(lightDiffuse);
		lightDiffuseBuffer.position(0);
		
		byteBuf = ByteBuffer.allocateDirect(lightPosition.length * 4);
		byteBuf.order(ByteOrder.nativeOrder());
		lightPositionBuffer = byteBuf.asFloatBuffer();
		lightPositionBuffer.put(lightPosition);
		lightPositionBuffer.position(0);
		
		mRelease = 0;
		mCube = null;
		mBackground = null;
		mWall = null;
		mSleep = false;
		mFirstImage = true;
		mError = 0;
		mText = null;
		mGL = null;
		curWikiImage = null;
		newWikiImage = null;
		mLastTextDisplay = 0;
		mAnimateText = false;
		mLight = false;
		mCanvasWidth = 0;
		mCanvasHeight = 0;
		mCanvasWidthThresh = 0;
		mCanvasHeightThresh = 0;
		mClearColorChanged = false;
		mClearColor = 0;
	 	mFadeOut = MAX_FADEOUT;
      	mFadeIn = MAX_FADEIN;
      	mMaxTexSize = 0;
      	xrot = yrot = zrot = 0.0f;
      	xtrans = ytrans = 0.0f;
      	xtrans_dir = 1;
      	ytrans_dir = 0;
      	mDisplayArtistImage = true;
      	mDisplayArtistVisible = true;
      	mCubeScale = true;
      	mCanvasRatio = 1.0f;
      	mSetBg = false;
      	mTextChanged = false;
      	mSurfaceChanged = false;
      	mStretchBg = true;
      	mStretchWall = false;
      	mTextColor = -1;
      	mTextSize = 40.0f;
      //	fpscounter = 0;
      //	fpstime = System.currentTimeMillis();
	}
	
	@Override
	public void onDrawFrame(GL10 gl) {		
    	//android.os.Debug.waitForDebugger();
		if ((mRelease & RELEASE_CUBE_TEX) != 0) {
			mCube.releaseTextures(gl);
			mFadeIn = MAX_FADEOUT;
		    mFadeOut = MAX_FADEOUT;
		}
		
		if ((mRelease & RELEASE_WALL_TEX) != 0) {
			mWall.releaseTextures(gl);
			mFadeIn = MAX_FADEOUT;
		   	mFadeOut = MAX_FADEOUT;
		}
		
		if (mRelease != 0)
			mRelease = 0;
		
		if (mSleep) {
			//Log.v("MS", "zzzz");
			SystemClock.sleep(200);
			return;
		}
		
		if (mClearColorChanged) {
			gl.glClearColor(mClearColorR, mClearColorG, mClearColorB, 0.5f);
			 	mClearColorChanged = false;
		}
		
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glPushMatrix();
		gl.glLoadIdentity();
		gl.glMatrixMode(GL10.GL_MODELVIEW); 
		gl.glPushMatrix();
		gl.glLoadIdentity(); 
		
		if ((mSetBg || mSurfaceChanged) && mBackground.getByteBuffer() != null) {
			mWall.releaseTextures(gl); //Just in case the texture didn't get released
			if (mStretchBg)
				mWall.setTexture(gl, mBackground, mCanvasWidth, mCanvasHeight, false, false, true);
			else
				mWall.setTexture(gl, mBackground, mCanvasWidth, mCanvasHeight, false, false, false);

			mSetBg = false;
		}
		
		if (mBackground.getByteBuffer() != null) {
			mWall.draw(gl, 1.0f);
		}
		
		if (mFirstImage && mError == ERROR_NOERROR) {
			mText.addText(gl, LOAD_MSG);
			mText.draw(gl);
		} else if (mFirstImage && mError != ERROR_NOERROR) {
			if (mError == ERROR_NOARTIST) {
				mText.addText(gl, DISK_ERROR);
				mText.draw(gl);
			}
			else if (mError == ERROR_MAXRETRIES) {
				mText.addText(gl, LOAD_ERROR);
				mText.draw(gl);
			} else {
				mText.addText(gl, GENERIC_ERROR);
				mText.draw(gl);
			}
		}

		if (curWikiImage == null || curWikiImage.getByteBuffer() == null || mSettingBackground) {		
			gl.glMatrixMode(GL10.GL_PROJECTION);
			gl.glPopMatrix();
			gl.glMatrixMode(GL10.GL_MODELVIEW); 
			gl.glPopMatrix();
			SystemClock.sleep(200); 
			
			return;
		} 
		
		if (mFirstImage) {
			mFirstImage = false;
			gl.glMatrixMode(GL10.GL_PROJECTION);
			gl.glPopMatrix();
			gl.glMatrixMode(GL10.GL_MODELVIEW); 
			gl.glPopMatrix();
			return;
		}

		long cur = System.currentTimeMillis();
		if (!mLight)
			gl.glDisable(GL10.GL_LIGHTING);
		else
			gl.glEnable(GL10.GL_LIGHTING);
	
		if (mFadeIn == MAX_FADEOUT && mFadeOut == MAX_FADEOUT && newWikiImage != null && 
				curWikiImage != newWikiImage) {
			curWikiImage = newWikiImage;
			if (mImageDisplay == CUBE_MODE)
				mCube.releaseTextures(gl);
			else
				mWall.releaseTextures(gl);
		
			newWikiImage = null;
		}
		
		if ((mFadeIn == MAX_FADEOUT && mFadeOut == MAX_FADEOUT) || mTextChanged || mSurfaceChanged) {
			mText.addText(gl, curWikiImage.getText());
			mTextChanged = false;
		}
			
		if (mImageDisplay == WALL_MODE && ((mFadeIn == MAX_FADEOUT && mFadeOut == MAX_FADEOUT) || mSurfaceChanged)) {
			if (mStretchWall)
				mWall.setTexture(gl, curWikiImage, mCanvasWidth, mCanvasHeight, true, false, true);
			else
				mWall.setTexture(gl, curWikiImage, mCanvasWidth, mCanvasHeight, true, false, false);
		}
		
		if (mImageDisplay == ZOOM_MODE) {
			if ((mFadeIn == MAX_FADEOUT && mFadeOut == MAX_FADEOUT) || mSurfaceChanged) {
				mWall.setTexture(gl, curWikiImage, mCanvasWidth, mCanvasHeight, true, true, false);
				if (!mSurfaceChanged)
					xtrans = ytrans = 0.0f;
			}
			
			gl.glTranslatef(xtrans, ytrans, 0.0f);
			float change = 0.004f;
	
			if (xtrans_dir == 1 && xtrans + change <= curWikiImage.getZoomWidthDiff()) {
				xtrans += change;
			} else {
				xtrans_dir = -1;
			}


			if (xtrans_dir == -1 && xtrans - change >= -curWikiImage.getZoomWidthDiff())	{
				xtrans -= change;
			} else {
				xtrans_dir = 1;
			}

			if (ytrans_dir == 1 &&	ytrans + change <= curWikiImage.getZoomHeightDiff()) {
				ytrans += change;
			} else {
				ytrans_dir = -1;
			}

			if (ytrans_dir == -1 && ytrans - change >= -curWikiImage.getZoomHeightDiff())	{
				ytrans -= change;
			} else if (ytrans_dir == -1) {
				ytrans_dir = 1;
			} 

		}
		
		if (mImageDisplay == ZOOM_MODE || mImageDisplay == WALL_MODE) {
			if (mFadeOut > MAX_FADEOUT) {
				mWall.draw(gl, (float) mFadeOut/255.0f);
				mFadeOut = (mFadeOut - FADE_DIFF > MAX_FADEOUT) ? mFadeOut - FADE_DIFF : MAX_FADEOUT;
			} else if (mFadeIn < MAX_FADEIN) {	            		
				mWall.draw(gl, (float) mFadeIn/255.0f);
				mFadeIn = (mFadeIn + FADE_DIFF < MAX_FADEIN) ? mFadeIn + FADE_DIFF : MAX_FADEIN + FADE_DIFF;
			} else if (mFadeOut == MAX_FADEOUT && mFadeIn >= MAX_FADEIN) {
				if (mFadeIn == MAX_FADEIN + FADE_DIFF) {
					if (mDisplayArtistImage) {
			       		mAnimateText = true;
			       		mLastTextDisplay = 0;
					}
					
					mFadeIn = MAX_FADEIN;
				}
					
				mWall.draw(gl, 1.0f);
			}
		}
		
		if (mImageDisplay == CUBE_MODE) {
			if (mBackground != null && mBackground.getByteBuffer() != null) {
				mWall.draw(gl, 1.0f);   	
			}
			
			gl.glMatrixMode(GL10.GL_PROJECTION);
            gl.glLoadIdentity();
            GLU.gluPerspective(gl, 45.0f, mCanvasRatio, 0.1f, 100.0f);
            gl.glMatrixMode(GL10.GL_MODELVIEW);
			gl.glLoadIdentity();
			gl.glTranslatef(0.0f, 0.0f, curWikiImage.getCubeTrans());		

			if ((mFadeIn == MAX_FADEOUT && mFadeOut == MAX_FADEOUT) || mSurfaceChanged) {
				mCube.setTexture(gl, curWikiImage, (float) (mCanvasWidth - mCanvasWidthThresh), 
					(float) (mCanvasHeight - mCanvasHeightThresh), mCubeScale);
				mFadeIn = MAX_FADEIN;
				if (mDisplayArtistImage) {
					mAnimateText = true;
					mLastTextDisplay = 0;
				}
			}
			
			//gl.glScalef(curWikiImage.getCubeScale(), curWikiImage.getCubeScale(), 
			//			curWikiImage.getCubeScale());
			gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);
			gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);
			gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f);
     		gl.glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
     		xrot += 0.4f;
			yrot += 0.2f;
			zrot += 0.3f;
			mCube.draw(gl);
		}
		
		
		if (mAnimateText && mLastTextDisplay == 0) {
			mLastTextDisplay = System.currentTimeMillis();
		}
		
		if (mAnimateText) {
			mText.draw(gl);
		}
		
		if (mAnimateText && cur - mLastTextDisplay > 5000) {
			mAnimateText = false;
		}
		
		long curcur = System.currentTimeMillis();
		/*if (curcur - fpstime >= 1000) {
			Log.v("MS", "FPS: " + fpscounter);
			fpscounter = 0;
			fpstime = curcur;
		}*/
		long diff = curcur - cur;
		//fpscounter++;
		if (mImageDisplay != WALL_MODE || (mImageDisplay == WALL_MODE && (mFadeIn != MAX_FADEIN || 
				mAnimateText))) {
				if (diff < 33 && diff >= 0) { //30 fps for cube
					SystemClock.sleep(33 - diff);
				}
		} else { //1fps for wallpaper
			SystemClock.sleep(1000 - diff);
		} 
		
		if (mSurfaceChanged)
			mSurfaceChanged = false;
		
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glPopMatrix();
		gl.glMatrixMode(GL10.GL_MODELVIEW); 
		gl.glPopMatrix();
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {        	
		//Log.v("MS", "Surface changed with width: " + width + " height: " + height);
		
		if (height == 0) {
			height = 512;
			Log.e("Musician Slideshow", "Error while setting screen height");
		}
		
		if (width == 0) {
			width = 512;
			Log.e("Musician Slideshow", "Error while setting screen width");
		}
		
		if (width != mCanvasWidth || height != mCanvasHeight) {
			if (curWikiImage != null && curWikiImage.getByteBuffer() != null)
				curWikiImage.setScales(width, height);
			if (mImageDisplay == ZOOM_MODE) {
				xtrans = ytrans = 0.0f;
			}
			
			if (mBackground != null && mBackground.getByteBuffer() != null) {
				mBackground.setScales(width, height);
			}
		}
		
        mCanvasHeight = height;
        mCanvasWidth = width;
        if (mImageDisplay == CUBE_MODE) {
        	mCanvasHeightThresh = (double) mCanvasHeight * .30; //Give more leeway to cube images 
        	mCanvasWidthThresh = (double) mCanvasWidth * .30;
        } else {
        	mCanvasHeightThresh = (double) mCanvasHeight * .10;
        	mCanvasWidthThresh = (double) mCanvasWidth * .10;
        }
        
	   	double lgb2 = Math.log10(2);
        int heightExp = (int) Math.ceil(Math.log10(height)/lgb2);
        int widthExp = (int) Math.ceil(Math.log10(width)/lgb2);
        int texWidth = (int) Math.pow(2, widthExp);
	    int texHeight = (int) Math.pow(2, heightExp);   
	    if (texWidth <= 0 || texWidth > mMaxTexSize) {
	       	texWidth = mMaxTexSize;
	    }
        
	    if (texHeight <= 0 || texHeight > mMaxTexSize) {
	       	texHeight = mMaxTexSize;
	    }

	    
	    if (mGL != null && gl != mGL) {  //The surface can change at any time 
			if (mText != null)           //textures must be released from the old gl context
				mText.shutdown(mGL);     //to avoid memory leaks
			if (mWall != null) {
				mWall.releaseTextures(mGL);
			}
			if (mCube != null) {
				mCube.releaseTextures(mGL);
			}
			
	        mSurfaceChanged = true;
			mGL = gl;
		}  else if (mGL == null) {
			mGL = gl;
		} else if (gl == mGL) {
			if (mText != null)           //textures must be released from the old gl context
				mText.shutdown(gl);     //to avoid memory leaks
			if (mWall != null) {
				mWall.setSize(width, height);
			}
			if (mCube != null) {
				mCube.setSize(width, height);
			}
			
			mTextChanged = true;
		}
		
    	mText = new Text(width, height, texWidth, texHeight, mTextSize, mTextColor);     
        mText.initialize(gl);
        mCanvasRatio = (float) mCanvasWidth/mCanvasHeight;
        gl.glViewport(0, 0, width, height);
        //The preview mode shows a default image rather than downloading one        
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		//Set light parameters
		gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbientBuffer);		
 		gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuseBuffer);		
 		gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPositionBuffer);	
 		gl.glEnable(GL10.GL_COLOR_MATERIAL);
 		gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT_AND_DIFFUSE, lightAmbientBuffer);
 		gl.glEnable(GL10.GL_LIGHT0);
		int[] intbuf = new int[1];
		gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, intbuf, 0); //Get the max texture size
		mMaxTexSize = intbuf[0];
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
        gl.glClearDepthf(1.0f);
        gl.glEnable(GL10.GL_DEPTH_TEST); 			
		gl.glDepthFunc(GL10.GL_LEQUAL); 			
        gl.glShadeModel(GL10.GL_SMOOTH);
        gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glEnable(GL10.GL_DITHER);				
		gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glLoadIdentity();
		gl.glMatrixMode(GL10.GL_MODELVIEW); 
		gl.glLoadIdentity(); 
        setClearColor();
	}
	
	public void release() {
		lightAmbientBuffer = null;
    	lightDiffuseBuffer = null;
    	lightPositionBuffer = null;
    	
		if (mText != null)  {         
			mText.shutdown(mGL);     //to avoid memory leaks
			mText = null;
		}
		
		if (mWall != null) {
			mWall.releaseTextures(mGL);
			mWall = null;
		}
		
		if (mCube != null) {
			mCube.releaseTextures(mGL);
			mCube = null;
		}
			
		if (mBackground != null) {
			mBackground = null;
		}
		
		mGL = null;
   		curWikiImage = null;
   		newWikiImage = null;
   		return;
	}
	
	public void setRelease(int release) {
		mRelease = release;
	}
	
	public void setCube(Cube cube) {
		mCube = cube;
	}
	
	public void setWall(Wall wall) {
		mWall = wall;
	}
	
	public void setBackground(Background bg) {
		mBackground = bg;
	}
	
	public void setSleep(boolean sleep) {
		mSleep = sleep;
	}
	
	public void setError(int error) {
		mError = error;
	}
	
	public int getError() {
		return mError;
	}
	
	public void setText(Text text) {
		mText = text;
	}
	
	public int getCanvasHeight() {
		return mCanvasHeight;
	}
	
	public int getCanvasWidth() {
		return mCanvasWidth;
	}
	
	public void setCurWikiImage(WikiCommonsImage image) {
		if (mImageDisplay == CUBE_MODE)
			setRelease(RELEASE_CUBE_TEX);
		else
			setRelease(RELEASE_WALL_TEX);
		
		curWikiImage = image;
	}
	
	public void setNewWikiImage(WikiCommonsImage image) {
		if (mImageDisplay == CUBE_MODE)
			setRelease(RELEASE_CUBE_TEX);
		
		newWikiImage = image;
	}
	
	public void setImageDisplay(int display) {
		if (display == CUBE_MODE) {
        	mLight = true;
        	mCanvasHeightThresh = (double) mCanvasHeight * .30;
			mCanvasWidthThresh = (double) mCanvasWidth * .30;
		} else {
        	mLight = false;
        	mCanvasHeightThresh = (double) mCanvasHeight * .10;
			mCanvasWidthThresh = (double) mCanvasWidth * .10;
		}
	
		mImageDisplay = display;
		setClearColor();
	}
	
	public void animateText() {
		if (mFadeIn == MAX_FADEIN && mFadeOut == MAX_FADEOUT && mDisplayArtistVisible) {
				mAnimateText = true;
				mLastTextDisplay = 0;
		}
	}
	
	public void setClearColor() {
		int color;
		if (mImageDisplay == CUBE_MODE && mBackground != null && mBackground.getByteBuffer() == null) {
			color = mClearColor;
			mClearColorR = (0xFF & (color >> 16))/255.0f;
			mClearColorG = (0xFF & (color >> 8))/255.0f;
			mClearColorB = (0xFF & color)/255.0f;
		} else {
			mClearColorR = 0.0f;
			mClearColorG = 0.0f;
			mClearColorB = 0.0f;
			
		}
		
     	mClearColorChanged = true;
	}
	
	public void setClearColor(int color) {
		mClearColor = color;
	}
	
	public int getClearColor() {
		return mClearColor;
	}
	
	public int getImageDisplay() {
		return mImageDisplay;
	}
	
	public void setFadeIn(int fadeIn) {
		mFadeIn = fadeIn;
	}
	
	public void setFadeOut(int fadeOut) {
		mFadeOut = fadeOut;
	}
	
	public int getMaxTexSize() {
		return mMaxTexSize;
	}
	
	public void setDisplayArtistImage(boolean display) {
		mDisplayArtistImage = display;
	}
	
	public void setDisplayArtistVisible(boolean display) {
		mDisplayArtistVisible = display;
	}
	
	public boolean getDisplayArtistImage() {
		return mDisplayArtistImage;
	}
	
	public boolean getDisplayArtistVisible() {
		return mDisplayArtistVisible;
	}
	
	public void setCubeScale(boolean scale) {
		mFadeIn = MAX_FADEOUT;
		mFadeOut = MAX_FADEOUT;
		mCubeScale = scale;
		setRelease(RELEASE_CUBE_TEX);
	}
	
	public boolean getCubeScale() {
		return mCubeScale;
	}
	
	public void setTextColor(int color) {
		if (mText != null)
			mText.setColor(color);
		
		mTextColor = color;
		mTextChanged = true;
	}
	
	public int getTextColor() {
		return mTextColor;
	}
	
	public void setTextSize(float size) {
		if (mText != null)
			mText.setTextSize(size);
		
		mTextSize = size;
		mTextChanged = true;
	}
	
	public float getTextSize() {
		return mTextSize;
	}
	
	public float getCanvasRatio() {
		return mCanvasRatio;
	}
	
	public double getCanvasWidthThresh() {
		return mCanvasWidthThresh;
	}
	
	public double getCanvasHeightThresh() {
		return mCanvasHeightThresh;
	}
	
	public void setNewBg() {
		mSetBg = true;
	}
	
	public void settingBackground(boolean status) {
		mSettingBackground = status;
	}
	
	public void setStretchBg(boolean stretch) {
		if (stretch == mStretchBg)
			return;
		
		if (mImageDisplay == CUBE_MODE) {
			setRelease(RELEASE_WALL_TEX);
			mSetBg = true;
		}
		
		mStretchBg = stretch;

	}
	
	public boolean getStretchBg() {
		return mStretchBg;
	}
	
	public void setStretchWall(boolean stretch) {
		if (stretch == mStretchWall)
			return;
		
		if (mImageDisplay == WALL_MODE)
			setRelease(RELEASE_WALL_TEX);
		
		mStretchWall = stretch;
	}
	
	public boolean getStretchWall() {
		return mStretchWall;
	}
}